import { init, getModularity } from './getModularity.js';
import getH from './getH';
function localSearch(matrix, rnvec, edgeData = init(matrix), targetFunction, bestRnvec, w) {
  let getTargetValue;
  if (targetFunction === 'H') getTargetValue = getH;
  else if (targetFunction === 'G') getTargetValue = getModularity;
  const len = matrix.length;
  let bestModularity = getTargetValue(matrix, rnvec, edgeData, w);
  // function nodeLearning() {
  //   while (true) {
  //     const modularity = bestModularity;
  //     for (let i = 0; i < len; i++) {
  //       let linkNodes = [];
  //       for (let j = 0; j < len; j++) {
  //         if (matrix[i][j] === 1 && rnvec[i] !== rnvec[j] && i !== j) {
  //           linkNodes.push(j);
  //         }
  //       }
  //       for (let j = 0; j < linkNodes.length; j++) {
  //         const temp = rnvec[i];
  //         rnvec[i] = rnvec[j];
  //         const tempModularity = getTargetValue(matrix, rnvec, edgeData);
  //         if (tempModularity > bestModularity) {
  //           bestModularity = tempModularity;
  //         } else {
  //           rnvec[i] = temp;
  //         }
  //       }
  //     }
  //     if (modularity === bestModularity) break;
  //   }
  // }
  function getRowH(i) {
    let h_p = 0;
    let h_n = 0;
    for (let j = 0; j < len; j++) {
      if (rnvec[i] === rnvec[j] && matrix[i][j] === -1 && i != j) {
        h_n++;
      } else if (rnvec[i] !== rnvec[j] && matrix[i][j] === 1 && i != j) {
        h_p++;
      }
    }
    return -(h_p + h_n);
  }
  function nodeLearning() {
    while (true) {
      const modularity = bestModularity;
      for (let i = 0; i < len; i++) {
        let linkNodes = [];
        for (let j = 0; j < len; j++) {
          if (matrix[i][j] === 1 && rnvec[i] !== rnvec[j] && i !== j) {
            linkNodes.push(j);
          }
        }
        for (let j = 0; j < linkNodes.length; j++) {
          const temp = rnvec[linkNodes[j]];
          const rowH1 = getRowH(linkNodes[j]);
          rnvec[linkNodes[j]] = rnvec[i];
          const rowH2 = getRowH(linkNodes[j]);
          const deltaH = rowH2 - rowH1;
          // const tempModularity = getTargetValue(matrix, rnvec, edgeData, w);
          // if (tempModularity > bestModularity) {
          //   const a = tempModularity - bestModularity;
          //   bestModularity = tempModularity;
          // } else {
          //   rnvec[linkNodes[j]] = temp;
          // }
          if (deltaH > 0) {
            bestModularity += deltaH;
          } else {
            rnvec[linkNodes[j]] = temp;
          }
        }
      }
      if (modularity === bestModularity) break;
    }
  }
  function clusterLearning() {
    const labels = [...new Set(rnvec)];
    for (let i = 0; i < labels.length; i++) {
      let target = bestModularity;
      for (let j = i + 1; j < labels.length; j++) {
        const from = labels[i];
        const to = labels[j];
        const temp = [...rnvec];
        for (let k = 0; k < len; k++) {
          if (temp[k] === from) temp[k] = to;
        }
        const tempTarget = getTargetValue(matrix, temp, edgeData, w);
        if (tempTarget > target) {
          target = tempTarget;
          for (let q = 0; q < rnvec.length; q++) {
            rnvec[q] = temp[q];
          }
        }
      }
      if (target > bestModularity) {
        bestModularity = target;
        return true;
      }
    }
    return false;
  }
  function partitionLearning() {
    const rnvecSet = [...new Set(rnvec)];
    const communities = new Array(rnvecSet.length);
    for (let i = 0; i < rnvecSet.length; i++) {
      const temp = [];
      for (let j = 0; j < rnvec.length; j++) {
        if (rnvec[j] === rnvecSet[i]) {
          temp.push(j);
        }
      }
      communities[i] = temp;
    }
    // console.log(communities);
    let k = 0;
    for (let i = 0; i < communities.length; i++) {
      let temp = [];
      for (let j = 0; j < communities[i].length; j++) {
        temp.push(bestRnvec[communities[i][j]]);
      }
      temp = [...new Set(temp)];
      for (let p = 0; p < temp.length; p++) {
        k++;
        for (let j = 0; j < communities[i].length; j++) {
          if (temp[p] === bestRnvec[communities[i][j]]) {
            rnvec[communities[i][j]] = k;
          }
        }
      }
    }
    bestModularity = getTargetValue(matrix, rnvec, edgeData, w);
  }
  nodeLearning();
  while (true) {
    if (!clusterLearning()) break;
  }
  // console.log('before rnvec:');
  // console.log(rnvec);
  // console.log('best rnvec:');
  // console.log(bestRnvec);
  partitionLearning();
  // console.log('after rnvec:');
  // console.log(rnvec);
  nodeLearning();
  while (true) {
    if (!clusterLearning()) break;
  }
  return bestModularity;
}
export default localSearch;
